home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
lisp
/
kcl
/
akcl
/
akcl1615.lha
/
c
/
fasdump.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-12-06
|
33KB
|
1,449 lines
/* Copyright William F. Schelter All Rights Reserved.
Utility for writing out lisp objects and reading them in:
Basically it attempts to write out only those things which could
be written out using princ and reread. It just uses less space
and is faster.
Primitives for dealing with a `fasd stream'.
Such a stream is really an array containing some state and a lisp file stream.
Note that having *print-circle* == nil wil make this faster. gensyms will
still be dumped correctly in that case.
open_fasd
write_fasd_top
read_fasd_top
close_fasd
*/
#ifndef FAT_STRING
#include "include.h"
#endif
object coerce_stream();
object fasd_patch_sharp();
object siVPinit;
static int needs_patching;
struct fasd {
object stream; /* lisp object of type stream */
object table; /* hash table used in dumping or vector on input*/
object eof; /* lisp object to be returned on coming to eof mark */
object direction; /* holds Cnil or Kinput or Koutput */
object package; /* the package symbols are in by default */
object index; /* integer. The current_dump index on write */
object filepos; /* nil or the position of the start */
object table_length; /* On read it is set to the size dump array needed
or 0
*/
object evald_items; /* a list of items which have been eval'd and must
not be walked by fasd_patch_sharp */
};
struct fasd current_fasd;
enum circ_ind {
LATER_INDEX,
NOT_INDEXED,
FIRST_INDEX,
};
enum dump_type {
d_nil, /* dnil: nil */
d_eval_skip, /* deval o1: evaluate o1 after reading it */
d_delimiter, /* occurs after d_list,d_general and d_new_indexed_items */
d_enter_vector, /* d_enter_vector o1 o2 .. on d_delimiter , make a cf_data with
this length. Used internally by akcl. Just make
an array in other lisps */
d_cons, /* d_cons o1 o2: (o1 . o2) */
d_dot,
d_list, /* list* delimited by d_delimiter d_list,o1,o2, ... ,d_dot,on
for (o1 o2 . on)
or d_list,o1,o2, ... ,on,d_delimiter for (o1 o2 ... on)
*/
d_list1, /* nil terminated length 1 d_list1,o1 */
d_list2, /* nil terminated length 2 */
d_list3,
d_list4,
d_eval,
d_short_symbol,
d_short_string,
d_short_fixnum,
d_short_symbol_and_package,
d_bignum,
d_fixnum,
d_string,
d_objnull,
d_structure,
d_package,
d_symbol,
d_symbol_and_package,
d_end_of_file,
d_standard_character,
d_vector,
d_array,
d_begin_dump,
d_general_type,
d_sharp_equals, /* define a sharp */
d_sharp_value,
d_sharp_value2,
d_new_indexed_item,
d_new_indexed_items,
d_reset_index,
d_macro,
d_reserve1,
d_reserve2,
d_reserve3,
d_reserve4,
d_indexed_item3, /* d_indexed_item3 followed by 3bytes to give index */
d_indexed_item2, /* d_indexed_item2 followed by 2bytes to give index */
d_indexed_item1,
d_indexed_item0 /* This must occur last ! */
};
/* set whole structures! */
#define SETUP_FASD_IN(fd) do{ \
fas_stream= (fd)->stream->sm.sm_fp; \
dump_index = fix((fd)->index) ; \
current_fasd= * (fd);}while(0)
#define SAVE_CURRENT_FASD \
struct fasd old_fd; \
int old_dump_index = dump_index; \
FILE *old_fas_stream = fas_stream; \
int old_needs_patching = needs_patching; \
old_fd = current_fasd;
#define RESTORE_FASD \
current_fasd =old_fd ; \
dump_index= old_dump_index ; \
needs_patching = old_needs_patching ; \
fas_stream = old_fas_stream
#define FASD_SHARP_LIMIT 250 /* less than short_max */
#define SETUP_FASD_OUT(fasd) SETUP_FASD_IN(fasd)
#define dump_hash_table (current_fasd.table)
#define SIZE_D_CODE 8
#define SIZE_BYTE 8
#define SIZE_SHORT ((2*SIZE_BYTE) - SIZE_D_CODE)
/* this is not! the maximum short !! It is shorter */
#define SHORT_MAX ((1<< SIZE_SHORT) -1)
/* given SHORT extract top code (say 4 bits) and bottom byte */
#define TOP(i) (i >> SIZE_BYTE)
#define BOTTOM(i) (i & ~(~0 << SIZE_BYTE))
#define FASD_VERSION 2
FILE *fas_stream;
int dump_index;
struct htent *gethash();
void read_fasd1();
object extended_read();
#define DEBUG
#ifdef DEBUG
#define PUT(x) putc1((char)x,fas_stream)
#define GET() getc1()
#define FWRITE fwrite1
#define FREAD fread1
char *dump_type_names[]={ "d_nil",
"d_eval_skip",
"d_delimiter",
"d_enter_vector",
"d_cons",
"d_dot",
"d_list",
"d_list1",
"d_list2",
"d_list3",
"d_list4",
"d_eval",
"d_short_symbol",
"d_short_string",
"d_short_fixnum",
"d_short_symbol_and_package",
"d_bignum",
"d_fixnum",
"d_string",
"d_objnull",
"d_structure",
"d_package",
"d_symbol",
"d_symbol_and_package",
"d_end_of_file",
"d_standard_character",
"d_vector",
"d_array",
"d_begin_dump",
"d_general_type",
"d_sharp_equals",
"d_sharp_value",
"d_sharp_value2",
"d_new_indexed_item",
"d_new_indexed_items",
"d_reset_index",
"d_macro",
"d_reserve1",
"d_reserve2",
"d_reserve3",
"d_reserve4",
"d_indexed_item3",
"d_indexed_item2",
"d_indexed_item1",
"d_indexed_item0"};
int debug;
print_op(i)
{if (debug)
{if (i < d_indexed_item0 & i >= 0)
{printf("\n<%s>",dump_type_names[i]);}
else {printf("\n<indexed_item0:%d>",i -d_indexed_item0);}}
return i;
}
#define PUTD(str,i) putd(str,i)
putd(str,i)
char *str;
int i;
{if (debug)
{printf("{");
printf(str,i);
printf("}");}
putc(i,fas_stream);}
putc1(x)
int x;
{ if (debug) printf("(%x,%d,%c)",x,x,x);
putc(x,fas_stream);
fflush(stdout);
}
getc1()
{ int x;
x= getc(fas_stream);
if (debug) printf("(%x,%d,%c)",x,x,x);
fflush(stdout);
return x;
}
fread1(p,n1,n2,st)
FILE* st;
char *p;
int n1;
int n2;
{int i,j;
j=fread(p,n1,n2,st);
if(debug)
{printf("[");
n1=n1*n2;
for(i=0;i<n1; i++)
putc(p[i],stdout);
printf("]");
fflush(stdout);}
return j;
}
fwrite1(p,n1,n2,st)
FILE* st;
char *p;
int n1;
int n2;
{int i,j;
j=fwrite(p,n1,n2,st);
if(debug)
{printf("[");
n1=n1*n2;
for(i=0;i<n1; i++)
putc(p[i],stdout);
printf("]");}
return j;
}
int char_read;
#define GET_OP() (print_op(getc(fas_stream)))
#define PUT_OP(x) fputc(print_op(x),fas_stream)
#define DP(sw) sw /* if (debug) {printf("\ncase sw");} */
#define GETD(str) getd(str)
getd(str)
char *str;
{ int i = getc(fas_stream);
if(debug){
printf("{");
printf(str,i);
printf("}");}
return i;}
#define DPRINTF(a,b) do{if(debug) printf(a,b);} while(0)
#else
#define PUT(x) putc((char)x,fas_stream)
#define GET() getc(fas_stream)
#define GET_OP GET
#define PUT_OP PUT
#define FWRITE fwrite
#define FREAD fread
#define DP(sw) sw
#define PUTD(a,b) PUT(b)
#define GETD(a) GET()
#define DPRINTF(a,b)
#endif
#define D_TYPE_OF(byt) \
((enum dump_type )((unsigned int) byt & ~(~0 << SIZE_D_CODE)))
/* this field may be the top of a short for length, or part of an extended
code */
#define E_TYPE_OF(byt) ((unsigned int) byt >> (SIZE_D_CODE))
/* takes two bytes and reconstructs the SIZE_SHORT int from them after
dropping the code */
/* takes two bytes i and j and returns the SHORT associated */
#define LENGTH(i,j) MAKE_SHORT(E_TYPE_OF(i),(j))
#define MAKE_SHORT(top,bot) (((top)<< SIZE_BYTE) + (bot))
#define READ_BYTE1() getc(fas_stream)
#define GET4(varx ) \
do{int var=READ_BYTE1(); \
var |= (READ_BYTE1() << SIZE_BYTE); \
var |= (READ_BYTE1() << (2*SIZE_BYTE)); \
var |= (READ_BYTE1() << (3*SIZE_BYTE)); \
DPRINTF("{4byte:varx= %d}", var); \
varx=var;} while (0)
#define GET2(varx ) \
do{int var=READ_BYTE1(); \
var |= (READ_BYTE1() << SIZE_BYTE); \
DPRINTF("{2byte:varx= %d}", var); \
varx=var;} while (0)
#define GET3(varx ) \
do{int var=READ_BYTE1(); \
var |= (READ_BYTE1() << SIZE_BYTE); \
var |= (READ_BYTE1() << (2*SIZE_BYTE)); \
DPRINTF("{3byte:varx= %d}", var); \
varx=var;} while (0)
#define MASK ~(~0 << 8)
#define WRITE_BYTEI(x,i) putc((((x) >> (i*SIZE_BYTE)) & MASK),fas_stream)
#define PUT4(varx ) \
do{int var= varx ; \
DPRINTF("{4byte:varx= %d}", var); \
WRITE_BYTEI(var,0); \
WRITE_BYTEI(var,1); \
WRITE_BYTEI(var,2); \
WRITE_BYTEI(var,3);} while(0)
#define PUT2(var ) \
do{int v=var; \
DPRINTF("{2byte:var= %d}", v); \
WRITE_BYTEI(v,0); \
WRITE_BYTEI(v,1); \
} while(0)
#define PUT3(var ) \
do{int v=var; \
DPRINTF("{3byte:var= %d}", v); \
WRITE_BYTEI(v,0); \
WRITE_BYTEI(v,1); \
WRITE_BYTEI(v,2); \
} while(0)
/* constructs the first byte containing ecode and top
top either stands for something in extended codes, or for something
the top part of a SIZE_SHORT int
*/
#define MAKE_CODE(CODE,Top) \
((unsigned int)(CODE) | ((unsigned int)(Top) << SIZE_D_CODE))
/* write out two bytes encoding the enum d_code CODE and SHORT SH. */
#define PUT_CODE_AND_SHORT(CODE,SH) \
PUT(MAKE_CODE(CODE,TOP(SH))); \
PUT(BOTTOM(SH));
#define READ_SYMBOL(leng,pack,to) \
do {char *p=alloc_relblock(leng);\
FREAD(p,1,leng,fas_stream); \
string_register->st.st_fillp = \
string_register->st.st_dim = leng; \
string_register->st.st_self = p; \
to=(pack==Cnil ? make_symbol(string_register) : intern(string_register,pack)); }while(0)
#define READ_STRING(leng,loc) \
*loc = alloc_simple_string(leng); \
(*loc)->st.st_self=alloc_relblock(leng); \
FREAD((*loc)->st.st_self,1,leng,fas_stream);
/* if try_hash finds it we don't need to write the object
Otherwise we write the index type and the object
*/
#define NUMBER_ZERO_ITEMS (SHORT_MAX - (int) d_indexed_item0)
enum circ_ind
do_hash(obj,dot)
object obj;
int dot;
{ struct htent *e;
int i;
int result;
e=gethash(obj,dump_hash_table);
if (e->hte_key==OBJNULL)
/* We won't index things unless they have < -2 in the hash table */
{ if(type_of(obj)!=t_package) return NOT_INDEXED;
sethash(obj,dump_hash_table,make_fixnum(dump_index));
e=gethash(obj,dump_hash_table);
PUT_OP(d_new_indexed_item);
DPRINTF("{dump_index=%d}",dump_index);
dump_index++;
return FIRST_INDEX;}
i = fix(e->hte_value);
if (i == -1) return NOT_INDEXED; /* don't want to index this baby */
if (dot) PUT_OP(dot);
if ( i < -1)
{ e->hte_value = make_fixnum(dump_index);
PUT_OP(d_new_indexed_item);
DPRINTF("{dump_index=%d}",dump_index);
dump_index++;
return FIRST_INDEX;
}
if (i < (NUMBER_ZERO_ITEMS))
{PUT_OP(i+(int)d_indexed_item0); return LATER_INDEX;}
if (i < (2*SHORT_MAX - (int)d_indexed_item0))
{PUT_OP((int)d_indexed_item1);
PUTD("n=%d",i- NUMBER_ZERO_ITEMS);
return LATER_INDEX;
}
if (i < SHORT_MAX*SHORT_MAX)
{PUT_OP((int)d_indexed_item2);
PUT2(i);
return LATER_INDEX;
}
if (i < SHORT_MAX*SHORT_MAX*SHORT_MAX)
{PUT_OP((int)d_indexed_item3);
PUT3(i);
return LATER_INDEX;
}
else
FEerror("too large an index");
return LATER_INDEX;
}
object
write_fasd_top(obj,x)
object x,obj;
{struct fasd *fd = (struct fasd *) x->v.v_self;
if (fd->direction == Koutput)
SETUP_FASD_IN(fd);
else FEerror("bad value for open slot of fasd");
write_fasd(obj);
/* we could really allocate a fixnum and then smash its field if this
is to costly */
(fd)->index = make_fixnum(dump_index);
return obj;
}
/* It is assumed that anything passed to eval should be first
sharp patched, and that there will be no more patching afterwards.
The object returned might have arbitrary complexity.
*/
#define MAYBE_PATCH(result) \
if (needs_patching) result =fasd_patch_sharp(result,0)
object
read_fasd_top(x)
object x;
{ struct fasd *fd = (struct fasd *) x->v.v_self;
int i;
VOL int e=0;
object result;
SETUP_FASD_IN(fd);
frs_push(FRS_PROTECT, Cnil);
if (nlj_active) {
e = TRUE;
goto L;
}
needs_patching=0;
if (current_fasd.direction == Kinput)
{read_fasd1(GET_OP(),&result);
MAYBE_PATCH(result);
(fd)->index = make_fixnum(dump_index);
fd->direction=current_fasd.direction;
}
else
if(current_fasd.direction== Cnil) result= current_fasd.eof;
else
FEerror("Stream not open for input");
L:
frs_pop();
if (e) {
nlj_active = FALSE;
unwind(nlj_fr, nlj_tag);
fd->direction=Cnil;
return Cnil;
}
else
return result;
}
object Seq;
object siSPinit;
void Lmake_hash_table();
object
open_fasd(stream,direction,eof,tabl)
object stream,direction,eof,tabl;
{ object str=Cnil;
object result;
if(direction==Kinput)
{str=coerce_stream(stream,0);
if (tabl==Cnil)
tabl=alloc_simple_vector(0,aet_object);
else
check_type(tabl,t_vector);}
if(direction==Koutput)
{str=coerce_stream(stream,1);
if(tabl==Cnil) tabl=funcall_cfun(Lmake_hash_table,2,Ktest,Seq);
else
check_type(tabl,t_hashtable);}
check_type(str,t_stream);
result=alloc_simple_vector(sizeof(struct fasd)/sizeof(int),aet_object);
array_allocself(result,1,Cnil);
{struct fasd *fd= (struct fasd *)result->v.v_self;
fd->table=tabl;
fd->stream=stream;
fd->direction=direction;
fd->eof=eof;
fd->index=small_fixnum(0);
fd->package=symbol_value(Vpackage);
fd->filepos = make_fixnum(file_position(stream));
SETUP_FASD_IN(fd);
if (direction==Koutput){
PUT_OP((int)d_begin_dump);
PUTD("version=%d",FASD_VERSION);
PUT4(0); /* reserve space for the size of index array needed */
/* equivalent to: write_fasd(current_fasd.package);
except we don't want to index this, so that we can open
with an empty array.
*/
PUT_OP(d_package);
write_fasd(current_fasd.package->p.p_name);
}
else /* input */
{ object tem;
read_fasd1(GET_OP(),&tem);
if(tem!=current_fasd.table) FEerror("not positioned at beginning of a dump");
}
fd->index=make_fixnum(dump_index);
fd->filepos=current_fasd.filepos;
fd->package=current_fasd.package;
return result;
}}
object
close_fasd(ar)
object ar;
{ struct fasd *fd= (struct fasd *)(ar->v.v_self);
check_type(ar,t_vector);
if (type_of(fd->table)==t_vector)
/* input uses a vector */
{if (fd->table->v.v_self)
gset(fd->table->v.v_self,0,fix(fd->index),aet_object);
}
else
if(fd->direction==Koutput)
{clrhash(fd->table);
SETUP_FASD_IN(fd);
PUT_OP(d_end_of_file);
{int i = file_position(fd->stream);
if(type_of(fd->filepos) == t_fixnum)
{ file_position_set(fd->stream,fix(fd->filepos) +2);
/* record the length of array needed to read the indices */
PUT4(fix(fd->index));
/* move back to where we were */
file_position_set(fd->stream,i);
}}
}
/* else FEerror("bad fasd stream"); */
fd->direction=Cnil;
return ar;
}
#define HASHP(x) 1
#define TRY_HASH \
if(do_hash(obj,0)==LATER_INDEX) return;
write_fasd(obj)
object obj;
{ int j,leng;
/* hook for writing other data in fasd file */
/* check if we have already output the object in a hash table.
If so just record the index */
{
/* if dump_index is too large or the object has not been written before
we output it now */
switch(type_of(obj)){
case DP(t_cons:)
TRY_HASH;
/* decide how long we think this list is */
{object x=obj->c.c_cdr;
int l=0;
if (obj->c.c_car == siSsharp_comma)
{ PUT_OP(d_eval);
write_fasd(x);
break;}
while(1)
{ if(x==Cnil)
{PUT_OP(d_list1+l);
break;}
if(type_of(x)==t_cons)
{if ((int) d_list1 + ++l > (int) d_list4)
{PUT_OP(d_list);
break;}
else {x=x->c.c_cdr;
continue;}}
/* 1 to 4 done */
if(l==0)
{PUT_OP(d_cons);
write_fasd(obj->c.c_car);
write_fasd(obj->c.c_cdr);
return;}
else
{PUT_OP(d_list);
break;
}}}
WRITE_LIST:
write_fasd(obj->c.c_car);
obj=obj->c.c_cdr;
{int l=0;
while(1)
{if (type_of(obj)==t_cons)
{ enum circ_ind is_indexed=LATER_INDEX;
if(HASHP(t_cons)){
is_indexed=do_hash(obj,d_dot);
if (is_indexed == LATER_INDEX)
return;
if (is_indexed==FIRST_INDEX)
{ PUT_OP(d_cons);
write_fasd(obj->c.c_car);
write_fasd(obj->c.c_cdr);
return;}}
write_fasd(obj->c.c_car);
l++;
obj=obj->c.c_cdr;}
else
if(obj==Cnil)
{if (l> ((int) d_list4- (int) d_list1))
{PUT_OP(d_delimiter);}
return;}
else
{PUT_OP(d_dot);
write_fasd(obj);
return;}}}
case DP(t_symbol:)
if (obj==Cnil)
{PUT_OP(d_nil); return;}
TRY_HASH;
leng=obj->s.s_fillp;
if (current_fasd.package!=obj->s.s_hpack)
{{
if (leng< SHORT_MAX)
{PUT_OP(d_short_symbol_and_package);
PUTD("leng=%d",leng);}
else
{ j=leng;
PUT_OP(d_symbol_and_package);
PUT4(j);}}
write_fasd(obj->s.s_hpack);}
else
{ if (leng< SHORT_MAX)
{ PUT_OP(d_short_symbol);
PUTD("leng=%d",leng);}
else
{ j=leng;
PUT_OP(d_symbol);
PUT4(j);}
}
FWRITE(obj->s.s_self,1,leng,fas_stream);
break;
case DP(t_fixnum:)
leng=fix(obj);
if ((leng< (SHORT_MAX/2))
&& (leng > -(SHORT_MAX/2)))
{PUT_OP(d_short_fixnum);
PUTD("leng=%d",leng);}
else
{PUT_OP(d_fixnum);
j=leng;
PUT4(j);}
break;
case DP(t_character:)
PUT_OP(d_standard_character);
PUTD("char=%c",char_code(obj));
break;
case DP(t_string:)
leng=(obj)->st.st_fillp;
if (leng< SHORT_MAX)
{PUT_OP(d_short_string);
PUTD("leng=%d",leng);}
else
{j=leng;
PUT_OP(d_string);
PUT4(j);}
FWRITE(obj->st.st_self,1,leng,fas_stream);
break;
case DP(t_bignum:)
PUT_OP(d_bignum);
{int l = obj->big.big_length;
long *u = obj->big.big_self;
PUT4(l);
while (-- l >=0)
{PUT4(*u) ; u++;}
break;}
case DP(t_package:)
TRY_HASH;
PUT_OP(d_package);
write_fasd(obj->p.p_name);
break;
case DP(t_structure:)
TRY_HASH;
{int narg=S_DATA(obj->str.str_def)->length;
int i;
object name= S_DATA(obj->str.str_def)->name;
if(narg >= SHORT_MAX)
FEerror("Only dump structures whose length < ~a",1,make_fixnum(SHORT_MAX));
PUT_OP(d_structure);
PUTD("narg=%d",narg);
write_fasd(name);
for (i = 0; i < narg; i++)
write_fasd(structure_ref(obj,name,i));}
break;
case DP(t_array:)
TRY_HASH;
PUT_OP(d_array);
{ int leng=obj->a.a_dim;
int i;
PUT4(leng);
PUTD("elttype=%d",obj->a.a_elttype);
PUTD("rank=%d",obj->a.a_rank);
{int i;
if (obj->a.a_rank > 1)
{
for (i=0; i<obj->a.a_rank ; i++)
PUT4(obj->a.a_dims[i]);}}
for(i=0; i< leng ; i++)
write_fasd(aref(obj,i));}
break;
case DP(t_vector:)
TRY_HASH;
PUT_OP(d_vector);
{ int leng=obj->v.v_fillp;
PUT4 (leng);
PUTD("eltype=%d",obj->v.v_elttype);
{int i;
for(i=0; i< leng ; i++)
{write_fasd(aref(obj,i));}}}
break;
default:
PUT_OP(d_general_type);
prin1(obj,current_fasd.stream);
PUTD("close general:%c",')');
}}
}
object
fasd_patch_sharp_cons(x,depth)
int depth;
object x;
{
for (;;) {
x->c.c_car = fasd_patch_sharp(x->c.c_car,depth+1);
if (type_of(x->c.c_cdr) == t_cons)
x = x->c.c_cdr;
else {
x->c.c_cdr = fasd_patch_sharp(x->c.c_cdr,depth+1);
break;
}
}
}
object
fasd_patch_sharp(x,depth)
object x;
{ object p;
cs_check(x);
if (++depth > 1000)
{ object *p = current_fasd.table->v.v_self;
while(*p)
{ if (x== *p++ && type_of(x)!=t_spice) return x;}}
/* eval'd forms are already patched, and they might contain
circular structure */
{ object p = current_fasd.evald_items;
while (p != Cnil)
{ if (p->c.c_car == x) return x;
p = p->c.c_cdr;}}
switch (type_of(x)) {
case DP(t_spice:)
{ if (x->spc.spc_dummy >= current_fasd.table->v.v_dim)
FEerror("bad spice ref");
return current_fasd.table->v.v_self[x->spc.spc_dummy ];
}
case DP(t_cons:)
/*
x->c.c_car = fasd_patch_sharp(x->c.c_car,depth);
x->c.c_cdr = fasd_patch_sharp(x->c.c_cdr,depth);
*/
fasd_patch_sharp_cons(x,depth);
break;
case DP(t_vector:)
{
int i;
if ((enum aelttype)x->v.v_elttype != aet_object)
break;
for (i = 0; i < x->v.v_fillp; i++)
x->v.v_self[i] = fasd_patch_sharp(x->v.v_self[i],depth);
break;
}
case DP(t_array:)
{
int i, j;
if ((enum aelttype)x->a.a_elttype != aet_object)
break;
for (i = 0, j = 1; i < x->a.a_rank; i++)
j *= x->a.a_dims[i];
for (i = 0; i < j; i++)
x->a.a_self[i] = fasd_patch_sharp(x->a.a_self[i],depth);
break;
}
case DP(t_structure:)
{object def = x->str.str_def;
int i;
i=S_DATA(def)->length;
while (i--> 0)
structure_set(x,def,i,fasd_patch_sharp(structure_ref(x,def,i),depth));
break;
}
}
return(x);
}
static object sharing_table;
enum circ_ind
is_it_there(x)
object x;
{ struct htent *e;
object table=sharing_table;
switch(type_of(x)){
case t_cons:
case t_symbol:
case t_structure:
case t_array:
case t_vector:
case t_package:
e= gethash(x,table);
if (e->hte_key ==OBJNULL)
{sethash(x,table,make_fixnum(-1));
return FIRST_INDEX;
}
else
{int n=fix(e->hte_value);
if (n <0)
e->hte_value=make_fixnum(n-1);
return LATER_INDEX;}
break;
default:
return NOT_INDEXED;}}
object
find_sharing_top(x,table)
object x,table;
{sharing_table=table;
find_sharing(x);
return Ct;}
find_sharing(x)
object x;
{
cs_check(x);
BEGIN:
if(is_it_there(x)!=FIRST_INDEX) return;
switch (type_of(x)) {
case DP(t_cons:)
find_sharing(x->c.c_car);
x=x->c.c_cdr;
goto BEGIN;
break;
case DP(t_vector:)
{
int i;
if ((enum aelttype)x->v.v_elttype != aet_object)
break;
for (i = 0; i < x->v.v_fillp; i++)
find_sharing(x->v.v_self[i]);
break;
}
case DP(t_array:)
{
int i, j;
if ((enum aelttype)x->a.a_elttype != aet_object)
break;
for (i = 0, j = 1; i < x->a.a_rank; i++)
j *= x->a.a_dims[i];
for (i = 0; i < j; i++)
find_sharing(x->a.a_self[i]);
break;
}
case DP(t_structure:)
{object def = x->str.str_def;
int i;
i=S_DATA(def)->length;
while (i--> 0)
find_sharing(structure_ref(x,def,i));
break;
}
}
return;
}
object
read_fasd(i)
int i;
{object tem;
read_fasd1(i,&tem);
return tem;}
/* I am not sure if saving vs_top,vs_base is necessary */
object
lisp_eval(x)
object x;
{ object *b,*t;
SAVE_CURRENT_FASD;
b=vs_base;
t=vs_top;
vs_base=vs_top;
vs_push(x);
Leval();
x=vs_base[0];
vs_base=b;
vs_top=t;
RESTORE_FASD;
return x;
}
#define CHECK_CH(i) do{if ((i)==EOF & feof(fas_stream)) bad_eof();}while (0)
/* grow vector AR of general type */
grow_vector(ar)
object ar;
{ int len=ar->v.v_dim;
int nl=(int) (1.5*len);
char *p= (char *)AR_ALLOC(alloc_contblock,nl,object);
bcopy(ar->v.v_self,p,sizeof(object)* len);
ar->v.v_self= (object *)p;
ar->v.v_dim= ar->v.v_fillp=nl;
while(--nl >=len)
ar->v.v_self[nl]=Cnil;
}
bad_eof()
{ FEerror("Unexpected end of file",0);}
/* read one starting with byte i into location loc */
void
read_fasd1(i,loc)
object *loc;
int i;
{ object tem;
int leng;
BEGIN:
CHECK_CH(i);
switch(D_TYPE_OF(i))
{case DP(d_nil:)
*loc=Cnil;return;
case DP(d_cons:)
read_fasd1(GET_OP(),&tem);
*loc=make_cons(tem,Cnil);
loc= &((*loc)->c.c_cdr);
i=GET_OP();
goto BEGIN;
case DP(d_list1:) i=1;goto READ_LIST;
case DP(d_list2:) i=2;goto READ_LIST;
case DP(d_list3:) i=3;goto READ_LIST;
case DP(d_list4:) i=4;goto READ_LIST;
case DP(d_list:) i=(1<<30) ; goto READ_LIST;
READ_LIST:
while(1)
{int j;
if (--i < 0) {*loc=Cnil; return;}
DP(reading_list:) ;
j=GET_OP();
CHECK_CH(j);
if (j==d_delimiter)
{*loc=Cnil;
DPRINTF("{Read end of list(%d)}",i);
return;}
else
if(j==d_dot)
{ DPRINTF("{Read end of dotted list(%d)}",i);
read_fasd1(GET_OP(),loc);
return;}
else
{object tem;
DPRINTF("{Read next item in list(%d)}",i);
read_fasd1(j,&tem);
DPRINTF("{Item=",(debug >= 2 ? pp(tem) : 0));
DPRINTF("}",0);
*loc=make_cons(tem,Cnil);
loc= &((*loc)->c.c_cdr);}}
case DP(d_delimiter:)
case DP(d_dot:)
FEerror("Illegal op at top level");
break;
case DP(d_eval_skip:)
read_fasd1(GET_OP(),loc);
MAYBE_PATCH(*loc);
lisp_eval(*loc);
read_fasd1(GET_OP(),loc);
break;
case d_reserve1:
case d_reserve2:
case d_reserve3:
case d_reserve4:
FEerror("Op reserved for future use");
break;
case DP(d_reset_index:)
dump_index=0;
break;
case DP(d_short_symbol:)
leng=GETD("leng=%d");
leng = LENGTH(i,leng);
READ_SYMBOL(leng,current_fasd.package,tem);
*loc=tem;
return ;
case DP(d_short_symbol_and_package:)
{object pack;
leng=GETD("leng=%d");
leng = LENGTH(i,leng);
read_fasd1(GET_OP(),&pack);
READ_SYMBOL(leng,pack,tem);
*loc=tem;
return;}
case DP(d_short_string:)
leng=GETD("leng=%d");
leng = LENGTH(i,leng);
READ_STRING(leng,loc);
return;
case DP(d_string:)
{int j;
GET4(j);
READ_STRING(j,loc);
return;}
case DP(d_indexed_item3:)
GET3(i);goto INDEXED;
case DP(d_indexed_item2:)
GET2(i);goto INDEXED;
case DP(d_indexed_item1:)
i=GET()+ NUMBER_ZERO_ITEMS ; goto INDEXED;
default:
case DP(d_indexed_item0:)
i = i - (int) d_indexed_item0; goto INDEXED;
INDEXED:
*loc= current_fasd.table->v.v_self[i];
/* if object not yet built make pointer to it */
if(*loc==0)
{*loc=current_fasd.table->v.v_self[i]= alloc_object(t_spice);
(*loc)->spc.spc_dummy= i;
needs_patching=1;}
return;
/* the item`s' case does not return a value but is simply
a facility to allow convenient dumping of a list of registers
at the beginning, follwed by a delimiter. read continues on. */
case DP(d_new_indexed_items:)
case DP(d_new_indexed_item:)
{object tem;
int cindex,k;
k=GET_OP();
MORE:
cindex =dump_index;
DPRINTF("{dump_index=%d}",dump_index);
if (dump_index >= current_fasd.table->v.v_dim)
grow_vector(current_fasd.table);
/* grow the array */
current_fasd.table->v.v_self[dump_index++] = 0;
read_fasd1(k,loc);
current_fasd.table->v.v_self[cindex] = *loc;
if (i==d_new_indexed_items)
{int k=GET_OP();
if (k==d_delimiter)
{ DPRINTF("{Reading last of new indexed items}",0);
read_fasd1(GET_OP(),loc);
return;}
else {
goto MORE;
}}
return;
}
case DP(d_short_fixnum:)
{int leng=GETD("n=%d");
if (leng & (1 << (SIZE_SHORT -1)))
leng= leng - (1 << (SIZE_SHORT));
*loc=make_fixnum(leng);
return;}
case DP(d_fixnum:)
{int j;
GET4(j);
*loc=make_fixnum(j);
return;}
case DP( d_bignum:)
{int j;
object tem;
long *u;
GET4(j);
tem = alloc_object(t_bignum);
tem->big.big_length = j;
tem-> big.big_self = 0;
u = tem-> big.big_self = (long *) alloc_relblock(j*sizeof(long));
while ( --j >=0)
{ GET4(*u);
u++;}
*loc=tem; return;}
case DP(d_objnull:)
*loc=0; return;
case DP(d_structure:)
{ int narg,i,tem;
object name;
narg=GETD("narg=%d");
read_fasd1(GET_OP(),& name);
{ object *base=vs_top;
object *p = base;
vs_base=base;
vs_top = base + 1 + narg;
*p++ = name;
for (i=0; i < narg ; i++)
read_fasd1(GET_OP(),p++);
vs_base=base;
vs_top = p;
siLmake_structure();
*loc = vs_base[0];
vs_top=vs_base=base;
return;
}}
case DP(d_symbol:)
{int i; object tem;
GET4(i);
READ_SYMBOL(i,current_fasd.package,tem);
*loc=tem;
return ;}
case DP(d_symbol_and_package:)
{int i; object pack;
GET4(i);
read_fasd1(GET_OP(),&pack);
READ_SYMBOL(i,pack,*loc);
return;}
case DP(d_package:)
{object pack,tem;
read_fasd1(GET_OP(),&tem);
pack=find_package(tem);
if (pack==Cnil) FEerror("The package named ~a, does not exist",1,tem);
*loc=pack;
return ;}
case DP(d_standard_character:)
*loc=(code_char(GETD("char=%c")));
return;
case DP(d_vector:)
{int leng,j;
object y;
object x=alloc_object(t_vector);
GET4(leng);
x->v.v_elttype = GETD("v_elttype=%d");
x->v.v_dim=x->v.v_fillp=leng;
x->v.v_self=0;
x->v.v_displaced=Cnil;
x->v.v_hasfillp=x->v.v_adjustable=0;
array_allocself(x,0,Cnil);
for (j=0; j< leng ; j++)
{ DPRINTF("{vector_elt=%d}",j);
read_fasd1(GET_OP(),&y);
aset(x,j,y);}
*loc=x;
DPRINTF("{End of length %d vector}",leng);
return;}
case DP(d_array:)
{int leng,i;
object y;
object x=alloc_object(t_array);
GET4(leng);
x->a.a_elttype = GETD("a_elttype=%d");
x->a.a_dim=leng;
x->a.a_rank= GETD("a_rank=%d");
x->a.a_self=0;
x->a.a_displaced=Cnil;
x->a.a_adjustable=0;
if (x->a.a_rank > 0)
{ x->a.a_dims = (int *)alloc_relblock(sizeof(int)*(x->a.a_rank)); }
for (i=0; i< x->a.a_rank ; i++)
GET4(x->a.a_dims[i]);
array_allocself(x,0,Cnil);
for (i=0; i< leng ; i++)
{ read_fasd1(GET_OP(),&y);
aset(x,i,y);}
*loc=x;
return;}
case DP(d_end_of_file:)
current_fasd.direction =Cnil;
*loc=current_fasd.eof;
return;
case DP(d_begin_dump:)
{int vers=GETD("version=%d");
object tem;
if(vers!=FASD_VERSION)
FEerror("This file was dumped with FASD version ~a not ~a.",
2,make_fixnum(vers),make_fixnum(FASD_VERSION));}
{int leng;
GET4(leng);
current_fasd.table_length=make_fixnum(leng);}
read_fasd1(GET_OP(),&tem);
if (type_of(tem)==t_package || tem==Cnil)
{current_fasd.package = tem;
*loc=current_fasd.table;}
else FEerror("expected package");
return;
case DP(d_general_type:)
*loc=read_object_non_recursive(current_fasd.stream);
if(GETD("close general:%c")!=')') FEerror("general type not followed by ')'");
return;
/* Special type, the forms have been sharp patched separately
It is also arranged that it does not
*/
case DP(d_enter_vector:)
{object *base=vs_top,x,y;
extern object siSPmemory;
int print_only=0;
int n = 0;
object vv = siSPmemory->s.s_dbind,tem;
if (vv == Cnil) print_only = 1;
else
if (type_of(vv)!=t_cfdata) FEerror("bad VectorToEnter");
while ((i=GET_OP()) !=d_delimiter)
{int eval=(i==d_eval_skip);
if (print_only)
{ if (eval) princ_str("#!",Ct);
else if (i== d_eval)
princ_str("#.",Ct);}
if(eval) i=GET_OP();
read_fasd1(i, &tem);
MAYBE_PATCH(tem);
/* the eval entries don't enter it */
if (print_only) {princ(tem,Ct);
princ_str(";",Ct);
princ(make_fixnum(n));
princ_str("\n",Ct);}
else
{
if(eval)
lisp_eval(tem);
else
{if (n >= vv->cfd.cfd_fillp) FEerror("cfd too small");
vv->cfd.cfd_self[n++]=tem;}}}
if (print_only==0) vv->cfd.cfd_fillp = n;
*loc=vv;
return;
}
case DP(d_eval:)
{object tem;
read_fasd1(GET_OP(),&tem);
MAYBE_PATCH(tem);
*loc = lisp_eval(tem);
current_fasd.evald_items = make_cons(*loc,current_fasd.evald_items);
return;
}
}}
clrhash(table)
object table;
{int i;
if (table->ht.ht_nent > 0 )
for(i = 0; i < table->ht.ht_size; i++) {
table->ht.ht_self[i].hte_key = OBJNULL;
table->ht.ht_self[i].hte_value = OBJNULL;}
table->ht.ht_nent =0;}
object read_fasl_vector1();
object
read_fasl_vector(in)
object in;
{char ch;
while (1)
{ ch=readc_stream(in);
if (ch=='#')
{unreadc_stream(ch,in);
return read_fasl_vector1(in);}
if (ch== d_begin_dump){
unreadc_stream(ch,in);
break;}}
{object ar=open_fasd(in,Kinput,0,Cnil);
int n=fix(current_fasd.table_length);
object result,tem,last;
#ifdef HAVE_ALLOCA
current_fasd.table->v.v_self
= (object *)alloca(n*sizeof(object));
#else
current_fasd.table->v.v_self
= (object *)alloc_relblock(n*sizeof(object));
#endif
current_fasd.table->v.v_dim=n;
current_fasd.table->v.v_fillp=n;
gset( current_fasd.table->v.v_self,0,n,aet_object);
result=read_fasd_top(ar);
if (type_of(result) !=t_vector) goto ERROR;
last=result->v.v_self[result->v.v_fillp-1];
if(type_of(last)!=t_cons || last->c.c_car !=siSPinit)
goto ERROR;
current_fasd.table->v.v_self = 0;
close_fasd(ar);
return result;
ERROR: FEerror("Bad fasd stream ~a",1,in);
return Cnil;
}}
init_fasdump()
{
make_si_sfun("READ-FASD-TOP",read_fasd_top,1);
make_si_sfun("WRITE-FASD-TOP",write_fasd_top,2);
make_si_sfun("OPEN-FASD",open_fasd,4);
make_si_sfun("CLOSE-FASD",close_fasd,1);
/* make_si_sfun("FASD-I-DATA",fasd_i_macro,1); */
make_si_sfun("FIND-SHARING-TOP",find_sharing_top,2);
}